package com.shenqi.language.controller;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.SecurityUtils;
import com.shenqi.language.converter.VocabularyVOConverter;
import com.shenqi.language.domain.Category;
import com.shenqi.language.service.ICategoryService;
import com.shenqi.language.util.Constant;
import com.shenqi.language.vo.VocabularyVO;
import com.shenqi.language.vo.VocabularyWithUserMarkVO;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.shenqi.language.domain.Vocabulary;
import com.shenqi.language.service.IVocabularyService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 词条Controller
 * 
 * @author shenqi
 * @date 2025-08-05
 */
@RestController
@RequestMapping("/language/vocabulary")
public class VocabularyController extends BaseController
{
    @Autowired
    private IVocabularyService vocabularyService;

    @Autowired
    private ICategoryService categoryService;

    @Autowired
    RedisCache redisCache;
    /**
     * 查询词条列表
     */
    @PreAuthorize("@ss.hasPermi('language:vocabulary:list')")
    @GetMapping("/list")
    public TableDataInfo list(Vocabulary vocabulary)
    {
        startPage();
        List<Vocabulary> list = vocabularyService.selectVocabularyList(vocabulary);
        return getDataTable(list);
    }

    /**
     * 导出词条列表
     */
    @PreAuthorize("@ss.hasPermi('language:vocabulary:export')")
    @Log(title = "词条", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Vocabulary vocabulary)
    {
        List<Vocabulary> list = vocabularyService.selectVocabularyList(vocabulary);
        ExcelUtil<Vocabulary> util = new ExcelUtil<Vocabulary>(Vocabulary.class);
        util.exportExcel(response, list, "词条数据");
    }

    /**
     * 获取词条详细信息
     */
    @PreAuthorize("@ss.hasPermi('language:vocabulary:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(vocabularyService.selectVocabularyById(id));
    }

    /**
     * 新增词条
     */
    @PreAuthorize("@ss.hasPermi('language:vocabulary:add')")
    @Log(title = "词条", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Vocabulary vocabulary)
    {
        return toAjax(vocabularyService.insertVocabulary(vocabulary));
    }

    /**
     * 修改词条
     */
    @PreAuthorize("@ss.hasPermi('language:vocabulary:edit')")
    @Log(title = "词条", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Vocabulary vocabulary)
    {
        return toAjax(vocabularyService.updateVocabulary(vocabulary));
    }

    /**
     * 删除词条
     */
    @PreAuthorize("@ss.hasPermi('language:vocabulary:remove')")
    @Log(title = "词条", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(vocabularyService.deleteVocabularyByIds(ids));
    }


    @GetMapping("/listUnderCategory/{categoryId}")
    public TableDataInfo listUnderCategory(@PathVariable Long categoryId) {
        // 这个方法进来的可能是父id，也可能是子ID，如果进来的是子ID，则查不到子下面的子类(三级)。所以应该把进来的ID也一起查询
        List<Category> cates = categoryService.findAllNodesByParentId(categoryId);
        List<Long> categoryIds = cates.stream().map(Category::getId)
                .collect(Collectors.toList());
        categoryIds.add(categoryId);
        startPage();
        List<Vocabulary> list = vocabularyService.findVocabularyUnderCategory(categoryIds);
        // 先获取分页信息
        TableDataInfo tableDataInfo = getDataTable(list);
        // 然后转换VO
        List<VocabularyVO> out = VocabularyVOConverter.INSTANCE.toVOList(list);
        tableDataInfo.setRows(out);
        return tableDataInfo;
    }

    /**
     * 查询带有标记的
     * @param categoryId
     * @param userMark 用户标记
     * @return
     */
    @GetMapping("/listUnderCategoryWithUserMark/{categoryId}")
    public TableDataInfo listUnderCategoryWithUserMark(@PathVariable Long categoryId,
                                                       @RequestParam(required = false) Integer userMark) {
        // 这个方法进来的可能是父id，也可能是子ID，如果进来的是子ID，则查不到子下面的子类(三级)。所以应该把进来的ID也一起查询
        // 增加缓存处理，不然有的目录太久了。
        List<Long> categoryIds = redisCache.getCacheObject(Constant.CACHE_KEY_CATEGORY + categoryId);
        if (categoryIds == null) {
            List<Category> cates = categoryService.findAllNodesByParentId(categoryId);
            categoryIds = cates.stream().map(Category::getId)
                    .collect(Collectors.toList());
            categoryIds.add(categoryId);
            redisCache.setCacheObject(Constant.CACHE_KEY_CATEGORY + categoryId, categoryIds,
                    1, TimeUnit.DAYS);
        }
        startPage();
        List<VocabularyWithUserMarkVO> list = vocabularyService.selectByCategoryIdsWithUserMark(categoryIds, userMark);
        return getDataTable(list);
        // 先获取分页信息
//        TableDataInfo tableDataInfo = getDataTable(list);
//        // 然后转换VO
//        List<VocabularyVO> out = VocabularyVOConverter.INSTANCE.toVOList(list);
//        tableDataInfo.setRows(out);
//        return tableDataInfo;
    }

    /**
     * 从当前分类及子类下随机取一个词条。
     * @param categoryId
     * @return
     */
    @GetMapping("/listRandomVocabulary/{categoryId}")
    public TableDataInfo listRandomVocabulary(@PathVariable Long categoryId) {
        // 这个方法进来的可能是父id，也可能是子ID，如果进来的是子ID，则查不到子下面的子类(三级)。所以应该把进来的ID也一起查询
        // 增加缓存处理，不然有的目录太久了。
        List<Long> categoryIds = redisCache.getCacheObject(Constant.CACHE_KEY_CATEGORY + categoryId);
        if (categoryIds == null) {
            List<Category> cates = categoryService.findAllNodesByParentId(categoryId);
            categoryIds = cates.stream().map(Category::getId)
                    .collect(Collectors.toList());
            categoryIds.add(categoryId);
            redisCache.setCacheObject(Constant.CACHE_KEY_CATEGORY + categoryId, categoryIds,
                    10, TimeUnit.DAYS);
        }
        List<Vocabulary> list = vocabularyService.selectRandomVocabularyList(categoryIds);
//        return getDataTable(list);
        // 先获取分页信息
        TableDataInfo tableDataInfo = getDataTable(list);
        // 然后转换VO
        List<VocabularyVO> out = VocabularyVOConverter.INSTANCE.toVOList(list);
        tableDataInfo.setRows(out);
        return tableDataInfo;
    }

    /**
     * 从当前分类及子类下随机取一个词条。
     * @param categoryId
     * @return
     */
    @GetMapping("/listRandomVocabularyWithUserMark")
    public TableDataInfo listRandomVocabularyWithUserMark(@RequestParam Long categoryId,
                                                          @RequestParam(required = false) Integer userMark,
                                                          @RequestParam(required = false) Boolean isSorted) {
        // 这个方法进来的可能是父id，也可能是子ID，如果进来的是子ID，则查不到子下面的子类(三级)。所以应该把进来的ID也一起查询
        // 增加缓存处理，不然有的目录太久了。
        List<Long> categoryIds = redisCache.getCacheObject(Constant.CACHE_KEY_CATEGORY + categoryId);
        if (categoryIds == null) {
            List<Category> cates = categoryService.findAllNodesByParentId(categoryId);
            categoryIds = cates.stream().map(Category::getId)
                    .collect(Collectors.toList());
            categoryIds.add(categoryId);
            redisCache.setCacheObject(Constant.CACHE_KEY_CATEGORY + categoryId, categoryIds,
                    10, TimeUnit.DAYS);
        }
        Long userId = SecurityUtils.getUserId();
        startPage();
        List<VocabularyWithUserMarkVO> list = vocabularyService.selectRandomVocabularyByCategoryIdsAndUserMark(categoryIds, userMark, userId, isSorted);
//        return getDataTable(list);
        // 先获取分页信息
        // TableDataInfo tableDataInfo = getDataTable(list);
        // 然后转换VO
        // List<VocabularyVO> out = VocabularyVOConverter.INSTANCE.toVOList(list);
        // tableDataInfo.setRows(out);
        return getDataTable(list);
    }


    /***
     * 获取某个分类下的各个标记的数量.
     */
    @GetMapping("listUserMarkCountByCategoryId")
    public AjaxResult listUserMarksCountByCategoryId(@RequestParam Long categoryId) {
        // 这个方法进来的可能是父id，也可能是子ID，如果进来的是子ID，则查不到子下面的子类(三级)。所以应该把进来的ID也一起查询
        // 增加缓存处理，不然有的目录太久了。
        List<Long> categoryIds = redisCache.getCacheObject(Constant.CACHE_KEY_CATEGORY + categoryId);
        if (categoryIds == null) {
            List<Category> cates = categoryService.findAllNodesByParentId(categoryId);
            categoryIds = cates.stream().map(Category::getId)
                    .collect(Collectors.toList());
            categoryIds.add(categoryId);
            redisCache.setCacheObject(Constant.CACHE_KEY_CATEGORY + categoryId, categoryIds,
                    10, TimeUnit.DAYS);
        }
        Long userId = SecurityUtils.getUserId();
        Map<String, Integer> marks = vocabularyService.countUserMarksByCategoryIds(categoryIds, userId);
        return success(marks);
    }
}
